
package main

import (
	"fmt"
	"strings"
	"os"
	"strconv"
)

func split(sum int) (x, y int) {
	x = sum * 4 / 9
	fmt.Println(x)
	y = sum - x
	fmt.Println(y)
	return
}

func main1() {
	fmt.Println("Hello, World");
}

func main2() {
	fmt.Println(strings.Join(os.Args[1:], " "))
}

// 修改echo程序，使其能够打印os.Args[0]
func main3() {
	fmt.Println(strings.Join(os.Args[0:], " "))
}

// 修改echo程序，使其打印value和index，每个value和index显示一行。
func main() {
	fmt.Println("Hello, World!")

   	var s = `Starting part
   	Ending part`
	
	fmt.Println(split(17))
	fmt.Println(s)
	// 声明，赋值 下面这些写法都是等价的:
	// s := "" 第一种形式，只能用在一个函数内部，而 package级别的变量不应该这么做。
	// var s string 第二种形式依赖于string类型的内部初始化机制，被初始化为空字符 串。
	// var s = "" 第三种形式使用得很少，除非同时声明多个变量。
	// var s string = "" 第四种形式会显式地标明变量的类型，在多变量 同时声明时可以用到。

	// 数组 Arrays
	var a = [5] int {1, 2, 3} // 长度为5的数组，其元素值依次为：1，2，3，0，0 。在初始化时没有指定初值的元素将会赋值为其元素类型int的默认值0,string的默认值是""
	fmt.Println(a)
	var b = [5] int {}
	fmt.Println(b)
	c := [...] int {1, 2, 3} // 长度为5的数组，其长度是根据初始化时指定的元素个数决定的
	fmt.Println(c)
	d := [5] int { 2:1,3:2,4:3} // 长度为5的数组，key:value,其元素值依次为：0，0，1，2，3。在初始化时指定了2，3，4索引中对应的值：1，2，3
	fmt.Println(d)
	e := [...] int {2:1,4:3} // 长度为5的数组，起元素值依次为：0，0，1，0，3。由于指定了最大索引4对应的值3，根据初始化的元素个数确定其长度为5
	fmt.Println(e)
	// f := [5] int {6:7}  //array index 6 out of bounds [0:5]
	// f := [5] int {1, 2, 3, 4, 5, 6} //array index 6 out of bounds [0:5]
	// fmt.Println(f)
	arr :=[...] int {1,2,3,4,5} // 数组通过下标访问元素，可修改其元素值
	arr[4]=arr[1]+len(arr)      //arr[4]=2+5
	fmt.Println(arr) // [1 2 3 4 7]

	arr1 := [5]int{5, 4, 3}

	for index, value := range arr1 { // 通过for遍历数组元素
		fmt.Printf("arr[%d]=%d \n", index, value)
	}

	for index := 0; index < len(arr1); index++ {
		fmt.Printf("arr[%d]=%d \n", index, arr[index])
	}

	arr2 := [5]int{1, 2} // 数组是值类型，将一个数组赋值给另一个数组时将复制一份新的元素
	arr5 := arr2
	arr5[0] = 5
	arr2[4] = 2
	fmt.Printf(" arr5= %d \n arr2=%d \n arr5[0]==arr2[0]= %v \n", arr5, arr2, arr5[0] == arr2[0])

	// 切片 Slices
	// 数组的长度不可改变，在特定场景中这样的集合就不太适用，Go中提供了一种灵活，
	// 功能强悍的内置类型Slices切片,与数组相比切片的长度是不固定的，可以追加元素，
	// 在追加时可能使切片的容量增大。切片中有两个概念：一是len长度，二是cap容量，
	// 长度是指已经被赋过值的最大下标+1，可通过内置函数len()获得。
	// 容量是指切片目前可容纳的最多元素个数，可通过内置函数cap()获得。
	// 切片是引用类型，因此在当传递切片时将引用同一指针，修改值将会影响其他的对象

	f :=[] int {1,2,3 } // 直接初始化切片，[]表示是切片类型，{1,2,3}初始化值依次是1,2,3.其cap=len=3
	fmt.Println(f)
	g := arr[:] // 初始化切片g,是数组arr的引用
	fmt.Println(g)
	h := arr[1:2] // arr[startIndex:endIndex]  将arr中从下标startIndex到endIndex-1 下的元素创建为一个新的切片
	fmt.Println(h)
	h[0]=110
	fmt.Println(h) // 切片生成的子切片将引用同一指针
	fmt.Println(arr)
	i := g[1:2] // 通过切片g初始化切片i
	fmt.Println(i)
	i[0]=220
	fmt.Println(i) // 切片生成的子切片将引用同一指针
	fmt.Println(arr)
	j := make([]int,5,10) // 通过内置函数make()初始化切片s,[]int 标识为其元素类型为int的切片, cap可以不传
	fmt.Println(j)
	// 切片是引用类型，在使用时需要注意其操作。切片可以通过内置函数append(slice []Type,elems ...Type)追加元素，
	// elems可以是一排type类型的数据，也可以是slice,因为追加的一个一个的元素，因此如果将一个slice追加到另一个slice中需要带上"..."，
	// 这样才能表示是将slice中的元素依次追加到另一个slice中。另外在通过下标访问元素时下标不能超过len大小，如同数组的下标不能超出len范围一样。
	k := append(j,1,2,3,4)
	fmt.Println(k)
	fmt.Println(j)
	l := append(k,f...)
	fmt.Println(l)
	k[0] = 11
	fmt.Println(k)
	fmt.Println(j)

	// copy函数 用法
	m := []int{1,2,3}
	fmt.Println(m) //[1 2 3]
	n := copy(m,[]int{4,5,6,7,8,9})
	fmt.Println(m) //[4 5 6]
	fmt.Println(n)

	o := []byte("hello world")
	p := copy(o,"ha ha")
	fmt.Println(o)
	fmt.Println(p)

	s, sep := "", " "
	for inx, arg := range os.Args[0:] {
		s += strconv.Itoa(inx) + sep + arg + `
		`
	}
	fmt.Println(s)

	fmt.Println(strings.Join(os.Args[1:], " "))
	fmt.Println(os.Args[1:])

	var xx = "wangguodong";
	str(xx)
	fmt.Println(xx)
}

// 证明字符串的传参是值传递
func str(s string) {
	s = "str"
}